/*
 * Copyright 2016-2019 yoara
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package yhao.infra.common.util;

import org.apache.commons.lang.StringUtils;

import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;

/**
 * 操作String的常用工具类
 *
 * @author yoara
 */
public class CommonStringUtil {
    /**
     * 带逗号分隔的数字转换为NUMBER类型
     *
     * @param str
     * @return
     * @throws ParseException
     */
    public static Number commaNumberStrToNumber(String str) throws ParseException {
        if (str == null || str.equals("")) {
            return null;
        }
        DecimalFormatSymbols dfs = new DecimalFormatSymbols();
        dfs.setDecimalSeparator('.');
        dfs.setGroupingSeparator(',');
        dfs.setMonetaryDecimalSeparator('.');
        DecimalFormat df = new DecimalFormat("###,###,###,###.##", dfs);
        return df.parse(str);
    }

    /**
     * 从文件名中获取后缀名
     *
     * @param filename
     * @return
     */
    public static String getExtensionName(String filename) {
        if ((filename != null) && (filename.length() > 0)) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length() - 1))) {
                filename = filename.substring(dot + 1);
                return filename == null ? filename : filename.toLowerCase();
            }
        }
        return filename == null ? filename : filename.toLowerCase();
    }

    /**
     * 删除末尾给定字符串
     *
     * @return
     */
    public static String removeEnd(String str, String remove) {
        if (StringUtils.isEmpty(str) || StringUtils.isEmpty(remove)) {
            return str;
        }
        if (str.endsWith(remove)) {
            return str.substring(0, str.length() - remove.length());
        }
        return str;
    }

    /**
     * 将字符串中的全角字符全部转成半角
     *
     * @param target 目标字符串
     * @return 转换后的字符串
     */
    public static final String fullHalfChange(String target) throws UnsupportedEncodingException {
        StringBuffer outStrBuf = new StringBuffer("");
        String Tstr = "";
        byte[] b = null;
        for (int i = 0; i < target.length(); i++) {
            Tstr = target.substring(i, i + 1);
            // 全角空格转换成半角空格
            if (Tstr.equals("　")) {
                outStrBuf.append(" ");
                continue;
            }
            b = Tstr.getBytes("unicode");
            // 得到 unicode 字节数据
            if (b[2] == -1) {
                // 表示全角？
                b[3] = (byte) (b[3] + 32);
                b[2] = 0;
                outStrBuf.append(new String(b, "unicode"));
            } else {
                outStrBuf.append(Tstr);
            }
        } // end for.
        return outStrBuf.toString();
    }

    /**字符串转int类型
     * @param str
     * @return
     */
    public static int stringToInt(String str) {
        int value = 0;
        if (StringUtils.isEmpty(str)) {
            return value;
        }
        try {
            value = Integer.parseInt(str);
        } catch (Exception e) {
        }
        return value;
    }

    /**
     * 判断包含数字
     **/
    public static boolean containNumeric(String str) {
        if (str == null || str.length() == 0) {
            return false;
        }
        for (int i = 0; i < str.length(); i++) {
            if (Character.isDigit(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断包含字母
     **/
    public static boolean containAlpha(String str) {
        if (str == null || str.length() == 0) {
            return false;
        }
        for (int i = 0; i < str.length(); i++) {
            if (Character.isLetter(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断一个字符是否是数字或者 "." , "-"
     */
    public static boolean isDigital(char c) {
        return (c >= '0' && c <= '9') || c == '.' || c == '-';
    }

    /**
     * 判断一个字符串是否全部是数字或者 "." , "-"组成
     */
    public static boolean isDigitalString(String value) {
        if (StringUtils.isEmpty(value))
            return false;
        for (int i = 0; i < value.length(); i++) {
            if (!isDigital(value.charAt(i)))
                return false;
        }
        return true;
    }

    /**
     * 判断一个字符是否是数字0-9
     */
    public static boolean isInt(char c) {
        return (c >= '0' && c <= '9');
    }

    /**
     * 判断一个字符串是否全部是数字0-9组成
     */
    public static boolean isIntString(String value) {
        if (StringUtils.isEmpty(value))
            return false;
        for (int i = 0; i < value.length(); i++) {
            if (!isInt(value.charAt(i)))
                return false;
        }
        return true;
    }

    /**
     * 判断一个字符是否是数字或者字符
     */
    public static boolean isAlphaOrDigital(char c) {
        return isDigital(c) || StringUtils.isAlpha(String.valueOf(c));
    }

    /**
     * 判断一个字符串是否全部是数字或者字符组成
     */
    public static boolean isAlphaOrDigital(String value) {
        if (StringUtils.isEmpty(value))
            return false;
        for (int i = 0; i < value.length(); i++) {
            if (!isAlphaOrDigital(value.charAt(i)))
                return false;
        }
        return true;
    }

    private static final char[] ChineseNum = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};
    private static final char[] ChineseUnit = {'里', '分', '角', '元', '拾', '佰', '仟', '万', '拾', '佰', '仟', '亿', '拾', '佰', '仟'};

    /**
     * 返回关于钱的中文式大写数字,支仅持到亿
     */
    public static String arabNumToChineseRMB(int moneyNum) {
        StringBuffer res = new StringBuffer();
        int i = 3;
        if (moneyNum == 0)
            return "零元";
        while (moneyNum > 0) {
            res.insert(0, ChineseUnit[i++]);
            res.insert(0, ChineseNum[moneyNum % 10]);
            moneyNum /= 10;
        }
        return res.toString().replaceAll("零[拾佰仟万]", "零")
                .replaceAll("零+亿", "亿").replaceAll("零+万", "万")
                .replaceAll("零+元", "元").replaceAll("零+", "零");

    }

    /**
     * 整数位支持12位,到仟亿
     * 支持到小数点后3位,如果大于3位,那么会四舍五入到3位
     *
     * @throws Exception
     */
    public static String arabNumToChineseRMB(double moneyNum) throws Exception {
        String res = "";
        String money = String.format("%.3f", moneyNum);
        int i = 0;
        if (moneyNum == 0.0)
            return "零元";
        String inte = money.split("\\.")[0];
        int deci = Integer.parseInt(money.split("\\.")[1].substring(0, 3));
        while (deci > 0) {
            res = ChineseUnit[i++] + res;
            res = ChineseNum[deci % 10] + res;
            deci /= 10;
        }
        res = res.replaceAll("零[里分角]", "零");
        if (i < 3)
            res = "零" + res;
        res = res.replaceAll("零+", "零");
        if (res.endsWith("零"))
            res = res.substring(0, res.length() - 1);
        int intMoney = Integer.parseInt(inte);
        return arabNumToChineseRMB(intMoney) + res;
    }

    /**
     * 根据身份编号获取性别
     *
     * @param idCard 身份编号
     * @return 性别(1 - 男 ， 2 - 女 ， N - 未知)
     */
    public static String getGenderByIdCard(String idCard) {
        String card = verifyIdCard(idCard);
        String sGender = "未知";
        String sCardNum = card.substring(16, 17);
        if (Integer.parseInt(sCardNum) % 2 != 0) {
            sGender = "1";//男
        } else {
            sGender = "2";//女
        }
        return sGender;
    }

    /**
     * 从身份证中提取出生日期
     * @return yyyy-MM-dd,不满足15或18位,返回空
     */
    public static String getBirthdayFromIdNo(String idNo) {
        if (idNo.length() == 15) {
            return new StringBuffer(
                    Integer.parseInt(idNo.substring(6, 8)) + 1900).append("-")
                    .append(idNo.substring(8, 10)).append("-").append(
                            idNo.substring(10, 12)).toString();
        } else if (idNo.length() == 18) {
            return new StringBuffer(idNo.substring(6, 10)).append("-").append(
                    idNo.substring(10, 12)).append("-").append(
                    idNo.substring(12, 14)).toString();
        } else {
            return "";
        }
    }

    /**
     * 根据身份编号获取生日
     *
     * @param idCard 身份编号
     * @return 生日(yyyyMMdd)
     */
    public static String getBirthByIdCard(String idCard) {
        String card = verifyIdCard(idCard);
        return card.substring(6, 14);
    }

    private static String verifyIdCard(String idCard) {
        if (StringUtils.isEmpty(idCard)) {
            throw new RuntimeException("身份证不得为空");
        }
        String _idCard = idCard.trim();
        if (_idCard.length() != 18) {
            throw new RuntimeException("仅支持18位身份证");
        }
        return _idCard;
    }

    /**
     * 字符串转大写方法
     * @param str 待转化字符串
     * @param camelCaseToUnderLine 是否将驼峰转化成下划线
     * @return
     */
    public static String toUpperCase(String str,boolean camelCaseToUnderLine){
        if(camelCaseToUnderLine){
            boolean firstChar = true;
            StringBuffer sb = new StringBuffer();
            char[] chars = str.toCharArray();
            for(char c:chars){
                if (Character.isUpperCase(c) && !firstChar) {
                    sb.append("_");
                }
                sb.append(c);
                firstChar = false;
            }
            return sb.toString().toUpperCase();
        }else{
            return str.toUpperCase();
        }
    }

    /**
     * sql like 字符串过滤
     *
     * like '%'||#{keyword}||'%' escape '\'
     */
    public static String sqlLikeStrFilter(String str){
        if(StringUtils.isEmpty(str)){
            return str;
        }
        return str.replaceAll("%","\\\\%").replaceAll("_","\\\\_");
    }
}
